package org.springblade.modules.repair.service.impl;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.repair.service.StsTokenService;
import org.springblade.modules.repair.vo.StsTokenVo;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class StsTokenServiceImpl implements StsTokenService {

	@Resource
	private Environment environment;

	private static final String REGION = "oss-cn-shenzhen";
	private static final String BUCKET = "erised-fresh";
	private static final String ENDPOINT = "sts.cn-shenzhen.aliyuncs.com";
	private static final String ACCESS_KEY_ID = "LTAI5tKREQNDYqtwMisLoXKn";
	private static final String ACCESS_KEY_SECRET = "9t92A3uvbKEj0WJGAgMuwvO3yDsYBx";
	private static final String ROLE_ARN = "acs:ram::1929435429577073:role/sts";
	private static final String ROLE_SESSION_NAME = "roleName";
	private static final String POLICY = "{\n" +
		"    \"Version\": \"1\",\n" +
		"    \"Statement\": [\n" +
		"        {\n" +
		"            \"Effect\": \"Allow\",\n" +
		"            \"Action\": [\n" +
		"                \"oss:PutObject\",\n" +
		"                \"oss:PutObjectAcl\",\n" +
		"                \"oss:PutObjectTagging\",\n" +
		"                \"oss:PutObjectVersionAcl\",\n" +
		"                \"oss:PutObjectVersionTagging\"\n" +
		"            ],\n" +
		"            \"Resource\": \"*\"\n" +
		"        }\n" +
		"    ]\n" +
		"}";

	private static final String OSS_CALLBACK_PROD = "https://repair-api.sida-tech.com/oss/callback";
	private static final String OSS_CALLBACK_TEST = "http://221.4.198.163:8650/oss/callback";
	private static final String OSS_CALLBACK_DEV = "http://221.4.198.163:8660/oss/callback";

	@Override
	public StsTokenVo getStsToken() throws com.aliyuncs.exceptions.ClientException {
		try {
			DefaultProfile.addEndpoint(REGION, "Sts", ENDPOINT);
			DefaultProfile profile = DefaultProfile.getProfile(REGION, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
			DefaultAcsClient client = new DefaultAcsClient(profile);
			AssumeRoleRequest request = new AssumeRoleRequest();
			request.setSysMethod(MethodType.POST);
			request.setRoleArn(ROLE_ARN);
			request.setRoleSessionName(ROLE_SESSION_NAME);
			request.setPolicy(POLICY);
			request.setDurationSeconds(3600L);
			final AssumeRoleResponse response = client.getAcsResponse(request);
			String expiration = response.getCredentials().getExpiration();

			String accessKeyId = response.getCredentials().getAccessKeyId();
			String accessKeySecret = response.getCredentials().getAccessKeySecret();
			String stsToken = response.getCredentials().getSecurityToken();
			String securityToken = response.getCredentials().getSecurityToken();
			String tenantId = AuthUtil.getTenantId();
			OSSClient ossClient = new OSSClient(ENDPOINT,accessKeyId,accessKeySecret);
//			long expireTime = 1L;
//			long expireEndTime = System.currentTimeMillis() + expireTime * 1000 * 60;
			// 将 expiration String 2024-07-09T03:36:30Z ISO 格式的时间转换为 Date 格式
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
			// 将 String 类型的时间转换为 Date 类型
			Date expirationDate = formatter.parse(expiration);
			// GMT 时间手动转换
			expirationDate.setTime(expirationDate.getTime() + 7 * 60 * 60 * 1000 + 2 * 60 * 1000);
			PolicyConditions policyConds = new PolicyConditions();
			policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
			//根据参数dir计算的policy，如果和前端uploadfile中参数key的相应字段不一致的话是会报错的
//			policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, uploadUrl);
			String postPolicy = ossClient.generatePostPolicy(expirationDate, policyConds);
			byte[] binaryData = postPolicy.getBytes();
			String encodedPolicy = BinaryUtil.toBase64String(binaryData);
			String postSignature = ossClient.calculatePostSignature(postPolicy);
			//业务完成一定要调用shutdown
			ossClient.shutdown();
			StsTokenVo token = StsTokenVo.builder().region(REGION).bucket(BUCKET).accessKeyId(accessKeyId).accessKeySecret(accessKeySecret)
				.stsToken(stsToken).expiration(expiration).securityToken(securityToken).tenantId(tenantId)
				.policy(encodedPolicy).signature(postSignature).build();

			//当前环境
			String curEnvironment = environment.getActiveProfiles()[0];
			if (Func.equalsSafe(curEnvironment, "prod")) {
				// 正式环境
				token.setCallBackUrl(OSS_CALLBACK_PROD);
			} else if(Func.equalsSafe(curEnvironment,"test")){
				// 测试环境
				token.setCallBackUrl(OSS_CALLBACK_TEST);
			}else {
				token.setCallBackUrl(OSS_CALLBACK_DEV);
			}
			return token;

		} catch (ClientException e) {
			e.printStackTrace();
		} catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return null;
	}

	@Override
	public Map<String, Object> getSignature() {
		String uploadUrl = "/upload";
		try {
			StsTokenVo stsToken = getStsToken();
			String accessId = stsToken.getAccessKeyId();
			String accessKey = stsToken.getAccessKeySecret();
			OSSClient ossClient = new OSSClient(ENDPOINT,accessId,accessKey);
			long expireTime = 30;
			long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
			Date expiration = new Date(expireEndTime);
			PolicyConditions policyConds = new PolicyConditions();
			policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
			//根据参数dir计算的policy，如果和前端uploadfile中参数key的相应字段不一致的话是会报错的
//			policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, uploadUrl);

			String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
			byte[] binaryData = postPolicy.getBytes();
			String encodedPolicy = BinaryUtil.toBase64String(binaryData);
			String postSignature = ossClient.calculatePostSignature(postPolicy);
			//业务完成一定要调用shutdown
			ossClient.shutdown();
			Map<String, Object> resultMap = new HashMap<String, Object>();
			resultMap.put("accessId",accessId);
			resultMap.put("policy", encodedPolicy);
			resultMap.put("signature", postSignature);
			return  resultMap;
		} catch (com.aliyuncs.exceptions.ClientException e) {
			throw new RuntimeException(e);
		}
	}

}
